package com.example.tool.util.ExpressDeliveryUtil;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.tool.util.ems.EMSApiUtil;
import com.example.tool.util.jt.JTApiUtil;
import com.example.tool.util.sto.StoApiUtil;
import com.example.tool.util.yto.YtoApiUtil;
import com.example.tool.util.yunda.YunDaApiUtil;
import com.example.tool.util.zto.ZtoApiUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.ARRIVAL;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.COLLECTION;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.DELIVERY;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.GIVEBACK;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.RECEIVED;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.SENDER;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.SIGNED;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.TRANSFER_ORDER;


public class ExpressDeliveryUtil {
    public static final String SF = "SF";
    public static final String YUN_DA = "YUNDA";
    public static final String ZTO = "ZTO";
    public static final String STO = "STO";
    public static final String JT = "JT";
    public static final String YTO = "YTO";
    public static final String EMS = "EMS";
    public static final String OTHER = "OTHER";
    public static final String UNKNOWN = "UNKNOWN";

    /**
     * 单号轨迹查询
     *
     * @param waybillNo
     * @return
     */
    public static ExpressDeliveryResult queryLogistics(String waybillNo) {
        List<ExpressDeliveryTrack> tracks = new ArrayList<>();
        ExpressDeliveryResult result = new ExpressDeliveryResult();
        result.setWaybillNo(waybillNo);
        result.setType(UNKNOWN);
        if (waybillNo == null || waybillNo.trim().isEmpty()) {
            return result;
        }
        // 统一格式：转大写+移除所有非字母数字字符
        String cleanedNo = waybillNo.toUpperCase().replaceAll("[^A-Z0-9]", "");
        // 各快递公司按匹配优先级排序
//        if (isSF(cleanedNo)) {
//       result.setType(SF);
//            JSONObject sfRqe = SFApiUtil.queryLogistics(waybillNo);
//            System.out.println(sfRqe);
//            JSONArray sfRetBody = sfRqe.getJSONArray("data").getJSONObject(0).getJSONArray("data");
//            IntStream.range(0, sfRetBody.size())
//            .map(i -> sfRetBody.size() - 1 - i)
//            .mapToObj(sfRetBody::getJSONObject)
//            .forEach(sfi -> {
//                ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
//                edt.setScanDate(toDate(sfi.getString("acceptTime")));
//                edt.setDesc(sfi.getString("remark"));
//                String state = sfi.getString("state");
//                String opcode = sfi.getString("opcode");
//                tracks.add(edt);
//            });
//            result.setTracks(tracks);
//            return result;
//        } else
        if (isYunDa(cleanedNo)) {
            // 获取令牌，如果超过速率限制则阻塞
            result.setType(YUN_DA);
            JSONObject ydRqe = YunDaApiUtil.queryLogistics(waybillNo);
            if (ObjectUtil.isNull(ydRqe) || !ydRqe.containsKey("data")) {
                return result;
            }
            Boolean resultFlag = ydRqe.getJSONObject("data").getBoolean("result");
            result.setSucceed(resultFlag);
            if (resultFlag) {
//             System.out.println(ydRqe.toJSONString());
                JSONArray ydResult = ydRqe.getJSONObject("data").getJSONArray("steps");
                ydResult = ObjectUtil.isNotNull(ydResult) ? ydResult : new JSONArray();
                IntStream.range(0, ydResult.size())
                        .mapToObj(ydResult::getJSONObject)
                        .forEach(yd -> {
                            ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
                            edt.setDesc(yd.getString("description"));
                            String scanType = "";
                            Boolean isCenter = false;
                            Boolean isTransfer = false;
                            switch (yd.getString("action")) {
                                case "GOT":
                                    scanType = COLLECTION.getCode();
                                    break;
                                case "DEPARTURE":
                                    scanType = SENDER.getCode();
                                    break;
                                case "ARRIVAL":
                                    scanType = RECEIVED.getCode();
                                    break;
                                case "INBOUND":
                                    scanType = ARRIVAL.getCode();
                                    break;
                                case "RETURN":
                                    scanType = GIVEBACK.getCode();
                                    break;
                                case "SENT":
                                    scanType = DELIVERY.getCode();
                                    break;
                                case "SIGNED":
                                    scanType = SIGNED.getCode();
                                    break;
                                case "TRANSFER_ORDER":
                                    scanType = TRANSFER_ORDER.getCode();
                                    break;
                            }
                            Integer stationType = yd.getInteger("station_type");
                            isTransfer = ObjectUtil.equals(stationType, 2);
                            isCenter = ObjectUtil.equals(stationType, 1);
                            edt.setScanDate(toDate(yd.getString("time")));
                            edt.setScanType(scanType);
                            edt.setIsCenter(isCenter);
                            edt.setIsTransfer(isTransfer);
                            tracks.add(edt);
                        });

            }
            result.setTracks(tracks);
            return result;
        } else if (isZTO(cleanedNo)) {
            result.setType(ZTO);
            JSONObject zopRqe = ZtoApiUtil.queryLogistics(waybillNo);
            Boolean status = zopRqe.getBoolean("status");
            result.setSucceed(status);
            if (status) {
                JSONArray zopResult = zopRqe.getJSONArray("result");
                System.out.println(zopResult.toJSONString());
                IntStream.range(0, zopResult.size())
                        .mapToObj(zopResult::getJSONObject)
                        .forEach(zop -> {
                            String desc = zop.getString("desc");
                            String scanType = zop.getString("scanType");
                            Long scanDate = zop.getLong("scanDate");
                            JSONObject scanSite = zop.getJSONObject("scanSite");
                            Boolean isCenter = scanSite.getString("isCenter").equals("T");
                            Boolean isTransfer = ObjectUtil.equals(scanSite.getInteger("isTransfer"), 1);
                            ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
//            if(scanType.equals("收件")){
                            if (scanType.equals("收件") && !isCenter && !isTransfer) {
                                edt.setScanType(COLLECTION.getCode());
                            }
                            if (scanType.equals("发件")) {
                                edt.setScanType(SENDER.getCode());
                            }
                            if (scanType.equals("到件")) {
                                edt.setScanType(RECEIVED.getCode());
                            }
                            if (scanType.equals("派件")) {
                                edt.setScanType(DELIVERY.getCode());
                            }
                            if (scanType.equals("退件")) {
                                edt.setScanType(GIVEBACK.getCode());
                            }
                            if (scanType.equals("转单")) {
                                edt.setScanType(TRANSFER_ORDER.getCode());
                            }
                            if (scanType.equals(ARRIVAL.getCode())) {
                                edt.setScanType(ARRIVAL.getCode());
                            }
                            if (scanType.equals("签收") || scanType.equals("第三方签收") || scanType.equals(SIGNED.getCode())) {
                                edt.setScanType(SIGNED.getCode());
                            }
                            edt.setScanDate(toDate(scanDate));
                            edt.setDesc(desc);
                            edt.setIsCenter(isCenter);
                            edt.setIsTransfer(isTransfer);
                            tracks.add(edt);
                        });
            }
            result.setTracks(tracks);
            return result;
        } else if (isSTO(cleanedNo)) {
            result.setType(STO);
            JSONObject stoRqe = StoApiUtil.queryLogistics(waybillNo);
            Boolean success = stoRqe.getBoolean("success");
            result.setSucceed(success);
            JSONArray stoRetBody = stoRqe.getJSONObject("data").getJSONArray(waybillNo);
            IntStream.range(0, stoRetBody.size()).
                    mapToObj(stoRetBody::getJSONObject).
                    forEach(sto -> {
                        ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
                        String scanType = "";
                        Boolean isCenter = false;
                        Boolean isTransfer = false;
                        switch (sto.getString("scanType")) {
                            case "收件":
                                scanType = COLLECTION.getCode();
                                break;
                            case "发件":
                                scanType = SENDER.getCode();
                                break;
                            case "到件":
                                scanType = RECEIVED.getCode();
                                break;
                            case "退回件":
                                scanType = GIVEBACK.getCode();
                                break;
                            case "驿站代收":
                            case "柜机代收":
                                scanType = ARRIVAL.getCode();
                                break;//派件
                            case "派件":
                            case "第三方代派":
                                scanType = DELIVERY.getCode();
                                break;//驿站签收
                            case "客户签收":
                            case "签收":
                                scanType = SIGNED.getCode();
                                break;//本人签收
                        }
                        String opOrgTypeCode = sto.getString("opOrgTypeCode");
                        edt.setScanDate(toDate(sto.getString("opTime")));
                        edt.setDesc(sto.getString("memo"));
                        edt.setScanType(scanType);
                        isTransfer = ObjectUtil.equal(opOrgTypeCode, "0003");
                        isCenter = ObjectUtil.equal(opOrgTypeCode, "0003");
                        edt.setIsCenter(isCenter);
                        edt.setIsTransfer(isTransfer);
                        tracks.add(edt);
                    });
            result.setTracks(tracks);
            return result;
        } else if (isJT(cleanedNo)) {
            result.setType(JT);
            result.setSucceed(true);
            JSONObject jtRqe = JTApiUtil.queryLogistics(waybillNo);
            JSONArray jtRetBody = jtRqe.getJSONArray("data").getJSONObject(0).getJSONArray("details");
            System.out.println(jtRetBody.toString());
            IntStream.range(0, jtRetBody.size()).
                    map(i -> jtRetBody.size() - 1 - i).
                    mapToObj(jtRetBody::getJSONObject).
                    forEach(jt -> {
                        ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
                        String scanType = jt.getString("scanType");
                        Boolean isCenter = false;
                        Boolean isTransfer = false;
                        switch (scanType) {
                            case "快件揽收":
                                scanType = COLLECTION.getCode();
                                break;
                            case "发件扫描":
                                scanType = SENDER.getCode();
                                break;
                            case "到件扫描":
                                scanType = RECEIVED.getCode();
                                break;
                            case "退件扫描":
                                scanType = GIVEBACK.getCode();
                                break;
                            case "出仓扫描":
                                scanType = DELIVERY.getCode();
                                break;//驿站签收
                            case "入库扫描":
                                scanType = ARRIVAL.getCode();
                                break;//派件
                            case "出库扫描":
                            case "快件签收":
                                scanType = SIGNED.getCode();
                                break;//本人签收
                        }
                        String networkType = jt.getString("networkType");
                        edt.setScanDate(toDate(jt.getString("scanTime")));
                        edt.setDesc(jt.getString("desc"));
                        edt.setScanType(scanType);
//            if(networkType.contains("中心")){
//            isTransfer=true;
//            isCenter=true;
//            }
//            isTransfer=JTApiUtil.isInTransferCenter(jt.getString("desc"));
                        isTransfer = Arrays.asList("中心", "网点").contains(networkType);
                        isCenter = !isTransfer;
                        edt.setIsCenter(isCenter);
                        edt.setIsTransfer(isTransfer);
                        tracks.add(edt);
                    });
            result.setTracks(tracks);
            return result;
        } else if (isYTO(cleanedNo)) {
            result.setType(YTO);
            JSONObject ytoRqe = YtoApiUtil.queryLogistics(waybillNo);
            Boolean succeed = ytoRqe.getBoolean("succeed");
            result.setSucceed(succeed);
//            JSONObject steps = ytoRqe.getJSONObject("map");
            JSONArray steps = ytoRqe.getJSONArray("steps");
//            System.out.println(steps.toString());
            IntStream.range(0, steps.size()).
                    mapToObj(steps::getJSONObject).
                    forEach(yto -> {
                        ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
                        String desc = yto.getString("processInfo");
                        edt.setDesc(desc);
                        edt.setScanDate(toDate(yto.getString("upload_Time")));
                        Boolean isCenter = false;
                        Boolean isTransfer = false;
                        String scanType = "";
                        switch (yto.getString("infoContent")) {
                            case "GOT":
                                scanType = COLLECTION.getCode();
                                break;
                            case "DEPARTURE":
                                scanType = SENDER.getCode();
                                break;
                            case "ARRIVAL":
                                scanType = RECEIVED.getCode();
                                break;
                            case "AIRSEND":
                                scanType = GIVEBACK.getCode();
                                break;
                            case "INBOUND":
                                scanType = ARRIVAL.getCode();
                                break;//入柜
                            case "SENT_SCAN":
                                scanType = DELIVERY.getCode();
                                break;//驿站签收
                            case "TMS_RETURN":
                                scanType = TRANSFER_ORDER.getCode();
                                break;//驿站签收
                            case "SIGNED":
                                scanType = SIGNED.getCode();
                                break;//本人签收
                        }
                        edt.setScanType(scanType);
//            if(desc.contains("到达")&&desc.contains("转运中心")&&scanType.equals(SENDER)){
//            isTransfer=true;
//            isCenter=true;
//            }
//            if(desc.contains("离开")&&desc.contains("转运中心")&&scanType.equals(RECEIVED)){
//            isTransfer=true;
//            isCenter=true;
//            }
                        isTransfer = YtoApiUtil.isInTransferCenter(desc);
                        isCenter = !isTransfer;
                        edt.setScanDate(toDate(yto.getString("upload_Time")));
                        edt.setIsCenter(isCenter);
                        edt.setIsTransfer(isTransfer);
                        tracks.add(edt);
                    });
            result.setTracks(tracks);
            return result;
        } else if (isEMS(cleanedNo)) {
            result.setType(EMS);
            JSONObject emsRqe = EMSApiUtil.queryLogistics(waybillNo);
            Boolean success = emsRqe.getBoolean("success");
            result.setSucceed(success);
            if (success) {
                JSONObject emsRetBody = emsRqe.getJSONObject("retBody");
                JSONArray responseItems = emsRetBody.getJSONArray("responseItems");
                responseItems.remove(0);
                IntStream.range(0, responseItems.size()).
                        mapToObj(responseItems::getJSONObject).
                        forEach(ems -> {
                            String opCode = ems.getString("opCode");
                            String opOrgName = ems.getString("opOrgName");
                            ExpressDeliveryTrack edt = new ExpressDeliveryTrack();
                            String scanType = "";
                            Boolean isCenter = false;
                            Boolean isTransfer = false;
                            switch (opCode) {
//            case "203": scanType=COLLECTION.getCode();break;//揽收 收寄计费信息203  揽收扫描配发345
                                case "345":
                                    scanType = COLLECTION.getCode();
                                    break;//揽收 收寄计费信息203  揽收扫描配发345
                                case "305":
                                case "989":
                                    scanType = SENDER.getCode();
                                    break;//发件
                                case "954":
                                case "713":
                                    scanType = RECEIVED.getCode();
                                    break;//到件
                                case "702":
                                    scanType = DELIVERY.getCode();
                                    break;//派件
                                case "312":
                                    scanType = GIVEBACK.getCode();
                                    break;//退回
                                case "747":
                                    scanType = ARRIVAL.getCode();
                                    break;//待签收
                                case "748":
                                    scanType = SIGNED.getCode();
                                    break;//签收
                            }

                            isCenter = !opOrgName.contains("中心");
                            //            if(opOrgName.contains("中心")){
                            isTransfer = opOrgName.contains("中心");
//            }
                            Date scanDate = toDate(ems.getString("opTime"));
                            String desc = ems.getString("opDesc");
                            edt.setDesc(desc);
                            edt.setScanDate(scanDate);
                            edt.setScanType(scanType);
                            edt.setIsTransfer(isTransfer);
                            edt.setIsCenter(isCenter);
                            tracks.add(edt);
                        });
            }

            result.setTracks(tracks);
            return result;
        } else {
            result.setType(OTHER);
            return result;
        }
    }

    /**
     * 单号轨迹更新订阅
     *
     * @param waybillNo
     * @return
     */
    public static void trackSubSubscribe(String waybillNo) {
        if (waybillNo == null || waybillNo.trim().isEmpty()) {
            return;
        }
        // 统一格式：转大写+移除所有非字母数字字符
        String cleanedNo = waybillNo.toUpperCase().replaceAll("[^A-Z0-9]", "");
        // 各快递公司按匹配优先级排序
//        if (isSF(cleanedNo)) {
//       result.setType(SF);

//        } else
        if (isYunDa(cleanedNo)) {
            YunDaApiUtil.trackSubSubscribe(waybillNo);
        } else if (isZTO(cleanedNo)) {
            ZtoApiUtil.trackSubSubscribe(waybillNo);
        } else if (isSTO(cleanedNo)) {
            StoApiUtil.trackSubSubscribe(waybillNo);
        } else if (isJT(cleanedNo)) {
            JTApiUtil.trackSubSubscribe(waybillNo);
        } else if (isYTO(cleanedNo)) {
            return;
//           YtoApiUtil.trackSubSubscribe(waybillNo)
        } else if (isEMS(cleanedNo)) {
            EMSApiUtil.trackSubSubscribe(waybillNo);
        }
    }

    // 顺丰 SF: 12位数字
    private static boolean isSF(String no) {
        return no.matches("^(SF)\\d{12,13}$");
    }

    // 韵达: 434或464开头，13-15位数字
    private static boolean isYunDa(String no) {
        return no.matches("^[34]\\d{14}$");
    }

    // 中通: 735/784/788开头，12-14位数字
    private static boolean isZTO(String no) {
        return no.matches("^(76|78|73)\\d{10,12}$");
    }

    // 申通: 773/772/777开头，12-15位数字
    private static boolean isSTO(String no) {
        return no.matches("^(773|772|777)\\d{9,12}$");
    }

    // 极兔: JT+11位数字 或 12位纯数字
    private static boolean isJT(String no) {
        return no.matches("^(JT)\\d{11,13}$");
    }

    // 圆通: YT+12位数字
    private static boolean isYTO(String no) {
        return no.matches("^(YT)\\d{12,13}$");
    }

    // EMS: 1开头 13位数字，
    private static boolean isEMS(String no) {
        return no.matches("^(1)\\d{12}$") || no.matches("^(98)\\d{11}$");
    }


//    public static ExpressDeliveryResult queryLogistics(String waybillNo){
//        ExpressDeliveryResult result =
//
//        new ExpressDeliveryResult();
//   /*     result.setWaybillNo(waybillNo);
//        result.setType("Unknown");
//        switch (detectExpress(waybillNo)){
////            case SF: o= SFApiUtil.queryLogistics(waybillNo);break;
////            case JT: o=JTApiUtil.queryLogistics(waybillNo);break;
////            case EMS: o=EMSApiUtil.queryLogistics(waybillNo);break;
////            case STO: o=StoApiUtil.queryLogistics(waybillNo);break;
////            case YTO: o=YtoApiUtil.queryLogistics(waybillNo);break;
////            case YUN_DA:o=YunDaApiUtil.queryLogistics(waybillNo);break;
//            case ZOP:
//                result.setType(ZOP);
//                JSONObject ZopResult=ZtoApiUtil.queryLogistics(waybillNo);
//                JSONArray ZopResultData = ZopResult.getJSONArray("result");
//
//
//                break;
//        }*/
//
//
//        return result;
//    }

    /**
     * 时间戳转date
     *
     * @param timestamp
     * @return
     */
    private static Date toDate(long timestamp) {
        return new Date(timestamp);
    }

    /**
     * 时间戳转date
     *
     * @param timestampStr
     * @return
     */
    private static Date toDate(String timestampStr) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return format.parse(timestampStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public static String judgeExpressDeliveryType(String waybillNo) {
        if (waybillNo == null || waybillNo.trim().isEmpty()) {
            return UNKNOWN;
        }
        String cleanedNo = waybillNo.toUpperCase().replaceAll("[^A-Z0-9]", "");
        if (isYunDa(cleanedNo)) {
            return YUN_DA;
        } else if (isZTO(cleanedNo)) {
            return ZTO;
        } else if (isSTO(cleanedNo)) {
            return STO;
        } else if (isJT(cleanedNo)) {
            return JT;
        } else if (isYTO(cleanedNo)) {
            return YTO;
        } else if (isEMS(cleanedNo)) {
            return EMS;
        } else {
            return OTHER;
        }
    }

    public static void main(String[] args) {
        System.out.println(queryLogistics("1398665420502"));
    }
//    public static void main(String[] args) throws JsonProcessingException {
    /// /        ExpressDeliveryResult result = queryLogistics("21");
    /// /        System.out.println(result);
    /// /        List<ExpressDeliveryTrack> tracks = new ArrayList<>();
    /// /        ExpressDeliveryTrack result1 = new ExpressDeliveryTrack();
    /// /        result1.setScanDateStr("2025-04-16 00:42:33");
    /// /        result1.setScanType("1");
    /// /        tracks.add(result1);
    /// /        ExpressDeliveryTrack result2 = new ExpressDeliveryTrack();
    /// /        result2.setScanType("3");
    /// /        result2.setScanDateStr("2025-04-16 13:42:33,");
    /// /        tracks.add(result2);
    /// /        ExpressDeliveryTrack result3 = new ExpressDeliveryTrack();
    /// /        result3.setScanType("3");
    /// /        result3.setScanDateStr("2025-04-26 0:42:33,");
    /// /        tracks.add(result3);
    /// /        boolean b = hasExcessiveTimeGaps(tracks,new Date());
    /// /        System.out.println(b);
//        System.out.println(queryLogistics("YT8774979893891"));
//
//    }

    private static final long SIXTEEN_HOURS_IN_MS = 16 * 60 * 60 * 1000; // 16小时的毫秒数

    public static boolean hasExcessiveTimeGaps(List<ExpressDeliveryTrack> tracks, Date now) {
        if (tracks == null || tracks.size() <= 1) {
            return false; // 少于两条记录不需要判断
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        boolean b = tracks.stream().filter(t -> !ObjectUtil.equal(t.getScanType(), "SIGNED")).count() > 1;
        tracks = tracks.stream().filter(t -> !ObjectUtil.equal(t.getScanType(), "SIGNED")).collect(Collectors.toList());

//        try {
           /* // 从第一条记录开始检查
            Date prevDate = sdf.parse(tracks.get(0).getScanDateStr());
            String prevScanType = tracks.get(0).getScanType();

            for (int i = 1; i < tracks.size(); i++) {
                ExpressDeliveryTrack currentTrack = tracks.get(i);
                Date currentDate = sdf.parse(currentTrack.getScanDateStr());
                String currentScanType = currentTrack.getScanType();

                // 如果前一条或当前条是已签收，跳过检查
                if (!"SIGNED".equals(prevScanType) && !"SIGNED".equals(currentScanType)) {
                    long timeDiff = currentDate.getTime() - prevDate.getTime();
                    if (timeDiff > SIXTEEN_HOURS_IN_MS) {
                        return true; // 发现超过16小时的间隔
                    }
                }

                // 更新前一条记录信息
                prevDate = currentDate;
                prevScanType = currentScanType;
            }*/

        if (!tracks.isEmpty()) {
            long diffInMilliseconds = Math.abs(now.getTime() - tracks.get(tracks.size() - 1).getScanDate().getTime());
            long diffInHours = diffInMilliseconds / (1000 * 60 * 60);
            if (!b && (diffInHours > SIXTEEN_HOURS_IN_MS)) {
                return true; // 发现超过16小时的间隔
            }
        }

        // 检查最后一条记录与当前时间（如果需要）
        // 这里可以根据需求决定是否要检查

        return false;

//        } catch (ParseException e) {
//            e.printStackTrace();
//            return false; // 日期解析失败视为未超时
//        }
    }

}
